<template>
  <div id="webgl"></div>
</template>

<script setup lang="ts">
import { nextTick, onMounted } from "vue";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader, GLTF } from "three/addons/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
import * as THREE from "three";
// import earth_img from "../assets/PerspectiveCamera.png";
// 引入gltf模型加载库GLTFLoader.js
import Cesium_Air from "../assets/Cesium_Air.gltf";

// 创建3D场景对象Scene
const scene: THREE.Scene = new THREE.Scene();
//纹理贴图加载器TextureLoader
// const texLoader: THREE.TextureLoader = new THREE.TextureLoader();
// .load()方法加载图像，返回一个纹理对象Texture
// const texture: THREE.Texture = texLoader.load(earth_img);
// 创建GLTF加载器对象，GLTF是标准贴图，需要光线
const loader: GLTFLoader = new GLTFLoader();
loader.load(Cesium_Air, function (gltf: GLTF) {
  gltf.scene.name = "飞机";
  // const obj = gltf.scene.getObjectByName("飞机");
  // obj.children的所有子对象都是Mesh，改变Mesh对应颜色
  // obj.children.forEach(function (mesh) {
  //   mesh.material.color.set(0xffff00);
  // });
  // gltf.scene.traverse(function (obj) {
  //   if (obj.isMesh) {
  //     // 重新设置材质
  //     obj.material = new THREE.MeshLambertMaterial({
  //       color: 0xffffff,
  //     });
  //     // obj.material.map = texture;
  //   }
  // });
  // 返回的场景对象gltf.scene插入到threejs场景中
  scene.add(gltf.scene);

  let duckMesh: THREE.Object3D | undefined =
    gltf.scene.getObjectByName("Cesium_Air_1");
  if (duckMesh instanceof THREE.Mesh) {
    let duckGeometry: THREE.BufferGeometry = duckMesh.geometry;
    // 计算包围盒
    duckGeometry.computeBoundingBox();
    // 几何体居中
    duckGeometry.center();
    // 获取包围盒
    const duckBox: THREE.Box3 | null = duckGeometry.boundingBox;
    // 创建包围盒辅助器
    if (duckBox) {
      let boxHelper = new THREE.Box3Helper(duckBox, 0xff0000);
      scene.add(boxHelper);
      // 获取包围盒中心点
      const center: THREE.Vector3 = duckBox.getCenter(new THREE.Vector3());
      const pointMesh: THREE.Mesh = new THREE.Mesh(
        new THREE.SphereGeometry(0.1, 32, 32),
        new THREE.MeshBasicMaterial({ color: 0xff0000 })
      );
      scene.add(pointMesh);
      pointMesh.position.set(center.x, center.y, center.z);
    }

    // 获取包围球
    let duckSphere: THREE.Sphere | null = duckGeometry.boundingSphere;
    if (duckSphere) {
      const sphereMesh: THREE.Mesh = new THREE.Mesh(
        new THREE.SphereGeometry(duckSphere.radius, 32, 32),
        new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
      );
      scene.add(sphereMesh);
      sphereMesh.position.set(
        duckSphere.center.x,
        duckSphere.center.y,
        duckSphere.center.z
      );
    }
  }
});

// 加载已经压缩过的GLTF模型
// 实例化加载器draco
const dracoLoader: DRACOLoader = new DRACOLoader();
// 设置draco路径
dracoLoader.setDecoderPath("./draco/");
// 设置gltf加载器draco解码器
loader.setDRACOLoader(dracoLoader);

// 创建一个环境光
const ambientLight: THREE.AmbientLight = new THREE.AmbientLight(0xffffff, 1); // 白色，强度为1
scene.add(ambientLight);

// 定义threejs输出画布的尺寸(单位:像素px)
const width: number = window.innerWidth; //宽度
const height: number = window.innerHeight; //高度
// 实例化一个透视投影相机对象
const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(
  45,
  width / height,
  1,
  1000
);
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(0, 0, 100);
// //相机观察目标指向Threejs 3D空间中某个位置
camera.lookAt(0, 0, 0); //指向mesh对应的位置

// AxesHelper：辅助观察的坐标系
const axesHelper: THREE.AxesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

// 创建渲染器对象
const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();

renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.setClearColor(0xffffff, 1);
renderer.render(scene, camera);

// 设置相机控件轨道控制器OrbitControls
const controls: OrbitControls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
controls.addEventListener("change", function () {
  renderer.render(scene, camera); //执行渲染操作
}); //监听鼠标、键盘事件

function render() {
  renderer.render(scene, camera); //执行渲染操作
  requestAnimationFrame(render);
}
render();

onMounted(() => {
  const webglElement = document.getElementById("webgl");
  if (webglElement) webglElement.appendChild(renderer.domElement);
});
</script>
